package jiparada;

public class WorldJiparada {
	public static final char OBSTACLE = '#';
	public static final char EMPTY = '.';
	public static final char ROBOT = '*';
	public static final char GOAL = 'G';
	public static final char PATH = 'o';
	public static final char UNKNOWN = '-';
	char mapData[][];
	char auxiliar;
	
	int rows;
	int cols;
	PositionJiparada goalPos = null;
	PositionJiparada robotPos = null;
	
	private PositionJiparada NW,NE,SE,SW;

	WorldJiparada(char mazeData[][], PositionJiparada startPos, PositionJiparada goalPos) {
		this.mapData = mazeData;
		this.rows = mazeData.length;
		this.cols = mazeData[0].length;
		this.robotPos = startPos;
		this.goalPos = goalPos;
		NW = new PositionJiparada(0,0);
		NE = new PositionJiparada(0,this.cols-1);
		SE = new PositionJiparada(this.rows-1,this.cols-1);
		SW = new PositionJiparada(this.rows-1,0);
	}

	void putRobot(int r, int c) {
		robotPos.row = r;
		robotPos.col = c;
	}
	
	PositionJiparada getRobotPosition()
	{
		return robotPos;
	}

	PositionJiparada getGoalPos()
	{
		return goalPos;
	}
	
	char[][] getMapData()
	{
		return mapData;
	}

	void updateGoalPos(int direction)
	{
		int r = robotPos.row, c = robotPos.col;

		mapData[goalPos.row][goalPos.col]=auxiliar;
		
		switch (direction) {
		case DirectionsJiparada.E:
			if(NW.col<c+2)
				NW.col=c+2;
			if(SW.col<c+2)
				SW.col=c+2;
			
			if(r<=NW.row)
				goalPos.row= NW.row;
			else if (r>=SW.row)
				goalPos.row= SW.row;
			else
				goalPos.row = r;
			
			goalPos.col= NW.col;
			break;
			
		case DirectionsJiparada.NE:
			if(NW.col<c+2)
				NW.col = c+2;
			if(SW.col<c+2)
				SW.col = c+2;
			if(SW.row>r-2)
				SW.row = r-2;
			if(SE.row>r-2)
				SE.row = r-2;		
			
			goalPos.row= SW.row;
			goalPos.col= SW.col;
			break;
			
		case DirectionsJiparada.N:
			if(SE.row>r-2)
				SE.row=r-2;
			if(SW.row>r-2)
				SW.row=r-2;
			
			goalPos.row= SE.row;
			
			if(c<=SW.col)
				goalPos.col = SW.col;
			else if (c>=SE.col)
				goalPos.col = SE.col;
			else
				goalPos.col = c;
			
			break;
			
		case DirectionsJiparada.NW:
			if(NE.col>c-2)
				NE.col = c-2;
			if(SE.col>c-2)
				SE.col = c-2;
			if(SE.row>r-2)
				SE.row = r-2;
			if(SW.row>r-2)
				SW.row = r-2;
			
			goalPos.row= SE.row;
			goalPos.col= SE.col;
			break;
			
		case DirectionsJiparada.W:
			if(NE.col>c-2)
				NE.col=c-2;
			if(SE.col>c-2)
				SE.col=c-2;
			
			if(r<=NE.row)
				goalPos.row= NE.row;
			else if (r>=SE.row)
				goalPos.row= SE.row;
			else
				goalPos.row = r;
			
			goalPos.col= NE.col;
			break;
			
		case DirectionsJiparada.SW:
			if(SE.col>c-2)
				SE.col = c-2;
			if(NE.col>c-2)
				NE.col = c-2;
			if(NE.row<r+2)
				NE.row = r+2;
			if(NW.row<r+2)
				NW.row = r+2;
			
			goalPos.row= NE.row;
			goalPos.col= NE.col;
			break;
			
		case DirectionsJiparada.S:
			if(NE.row<r+2)
				NE.row=r+2;
			if(NW.row<r+2)
				NW.row=r+2;
			
			goalPos.row= NE.row;
			
			if(c<=NW.col)
				goalPos.col = NW.col;
			else if (c>=NE.col)
				goalPos.col = NE.col;
			else
				goalPos.col = c;
			
			break;
			
		case DirectionsJiparada.SE:
			if(SW.col<c+2)
				SW.col = c+2;
			if(NW.col<c+2)
				NW.col = c+2;
			if(NW.row<r+2)
				NW.row = r+2;
			if(NE.row<r+2)
				NE.row = r+2;
			
			goalPos.row= NW.row;
			goalPos.col= NW.col;
			break;
		default:
			throw new RuntimeException("Direction does not exist.");
		}
		auxiliar=mapData[goalPos.row][goalPos.col];
		mapData[goalPos.row][goalPos.col]=WorldJiparada.GOAL;
		
		/*System.out.println("NW.row: "+NW.row+" NW.col: "+NW.col);
		System.out.println("NE.row: "+NE.row+" NE.col: "+NE.col);
		System.out.println("SE.row: "+SE.row+" SE.col: "+SE.col);
		System.out.println("SW.row: "+SW.row+" SW.col: "+SW.col);*/
		
		//System.out.println("Goal row: "+goalPos.row+" Goal col. "+goalPos.col);
		
	}

	void moveRobot(int direction) {
		PositionJiparada newpos = null;
		int r = robotPos.row, c = robotPos.col;
		switch (direction) {
		case DirectionsJiparada.E:
			newpos = new PositionJiparada(r, c + 1);
			break;
		case DirectionsJiparada.NE:
			newpos = new PositionJiparada(r - 1, c + 1);
			break;
		case DirectionsJiparada.N:
			newpos = new PositionJiparada(r - 1, c);
			break;
		case DirectionsJiparada.NW:
			newpos = new PositionJiparada(r - 1, c - 1);
			break;
		case DirectionsJiparada.W:
			newpos = new PositionJiparada(r, c - 1);
			break;
		case DirectionsJiparada.SW:
			newpos = new PositionJiparada(r + 1, c - 1);
			break;
		case DirectionsJiparada.S:
			newpos = new PositionJiparada(r + 1, c);
			break;
		case DirectionsJiparada.SE:
			newpos = new PositionJiparada(r + 1, c + 1);
			break;
		default:
			throw new RuntimeException("Direction does not exist.");
		}
		if (mapData[newpos.row][newpos.col] != WorldJiparada.OBSTACLE) {
			mapData[robotPos.row][robotPos.col] = WorldJiparada.PATH;
			mapData[newpos.row][newpos.col] = WorldJiparada.ROBOT;
			robotPos = newpos;
		}
		// else don't move
	}

	boolean isVisited(int direction)
	{
		int r = robotPos.row, c = robotPos.col;

		if(direction==DirectionsJiparada.E)
			return (mapData[r][c+1]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.NE)
			return (mapData[r-1][c+1]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.N)
			return (mapData[r-1][c]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.NW)
			return (mapData[r-1][c-1]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.W)
			return (mapData[r][c-1]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.SW)
			return (mapData[r+1][c-1]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.S)
			return (mapData[r+1][c]==WorldJiparada.PATH);
		else if(direction==DirectionsJiparada.SE)
			return (mapData[r+1][c+1]==WorldJiparada.PATH);
		
		return true;
	}

	int getRows() {
		return rows;
	}

	int getCols() {
		return cols;
	}

	char getMazeData(int r, int c) {
		return mapData[r][c];
	}

	void setMazeData(char value, int r, int c)
	{
		mapData[r][c]=value;
	}

	void setMazeSorroundings(char surroundings[]) {

		int r = robotPos.row, c = robotPos.col;

		//if(mapData[r][c+1]!=WorldJiparada.OBSTACLE&&mapData[r][c+1]!=WorldJiparada.PATH && mapData[r][c+1]!=WorldJiparada.EMPTY)
		mapData[r][c+1]=surroundings[DirectionsJiparada.E];

		//if(mapData[r-1][c+1]!=WorldJiparada.OBSTACLE&&mapData[r-1][c+1]!=WorldJiparada.PATH)
		mapData[r-1][c+1]=surroundings[DirectionsJiparada.NE];

		//if(mapData[r-1][c]!=WorldJiparada.OBSTACLE&&mapData[r-1][c]!=WorldJiparada.PATH)
		mapData[r-1][c]=surroundings[DirectionsJiparada.N];

		//if(mapData[r-1][c-1]!=WorldJiparada.OBSTACLE&&mapData[r-1][c-1]!=WorldJiparada.PATH)
		mapData[r-1][c-1]=surroundings[DirectionsJiparada.NW];

		//if(mapData[r][c-1]!=WorldJiparada.OBSTACLE&&mapData[r][c-1]!=WorldJiparada.PATH)
		mapData[r][c-1]=surroundings[DirectionsJiparada.W];

		//if(mapData[r+1][c-1]!=WorldJiparada.OBSTACLE&&mapData[r+1][c-1]!=WorldJiparada.PATH)
		mapData[r+1][c-1]=surroundings[DirectionsJiparada.SW];

		//if(mapData[r+1][c]!=WorldJiparada.OBSTACLE&&mapData[r+1][c]!=WorldJiparada.PATH)
		mapData[r+1][c]=surroundings[DirectionsJiparada.S];

		//if(mapData[r+1][c+1]!=WorldJiparada.OBSTACLE&&mapData[r+1][c+1]!=WorldJiparada.PATH)
		mapData[r+1][c+1]=surroundings[DirectionsJiparada.SE];

	}
}
